﻿using Emgu.CV;
using Emgu.CV.Structure;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 仪表识别2
{
    class DataUtil
    {
        public DataUtil(string xText = "", string yText = "", int maxX = 400, int maxY = 400)
        {
            this.xText = xText;
            this.yText = yText;
            this.maxX = maxX;
            this.maxY = maxY;
        }
        //画布属性
        int dstWidth = 500;
        int dstHeight = 500;
        int padding = 50;

        //数据
        public PointF[] pointfs;

        public string xText = "";
        public string yText = "";
        public int maxX = 400;
        public int maxY = 400;
        public bool showMax = false;
        public bool showMin = false;
        //密集区域
        public bool showConcentratedArea = false;
        public int concentratedAreaRadius = 10;
        public int maxConcentratedNum = 30;
        public Image<Gray, byte> draw(Point[] points)
        {
            return draw(points);
        }
        public Image<Bgr, byte> draw(PointF[] pointfs)
        {
            this.pointfs = pointfs;
            
            Image<Bgr, byte> dst = new Image<Bgr, byte>(dstWidth, dstHeight).Not();
            double ratioX = maxX > 400 ? maxX / 400 : 1;
            double ratioY = maxY > 400 ? maxY / 400 : 1;

            //画坐标轴
            Point O = new Point(padding, 450);
            Point X = new Point(450, 450);
            Point Y = new Point(padding, padding);
            dst.Draw(new LineSegment2D(O, X), new Bgr(Color.Black), 1);
            dst.Draw(new LineSegment2D(O, Y), new Bgr(Color.Black), 1);
            dst.Draw(yText, new Point(5, padding / 2), Emgu.CV.CvEnum.FontFace.HersheyComplexSmall, 1, new Bgr(Color.Black));
            dst.Draw(xText, new Point(dstWidth - padding * 2, dstHeight - padding / 2), Emgu.CV.CvEnum.FontFace.HersheyComplexSmall, 1, new Bgr(Color.Black));
            //画箭头
            dst.Draw(new LineSegment2D(new Point(X.X - 10, X.Y - 10), X), new Bgr(Color.Black), 1);
            dst.Draw(new LineSegment2D(new Point(X.X - 10, X.Y + 10), X), new Bgr(Color.Black), 1);

            dst.Draw(new LineSegment2D(new Point(Y.X - 10, Y.Y + 10), Y), new Bgr(Color.Black), 1);
            dst.Draw(new LineSegment2D(new Point(Y.X + 10, Y.Y + 10), Y), new Bgr(Color.Black), 1);

            foreach (PointF p in pointfs)
            {
                Point pp = new Point((int)(p.X / ratioX + padding), (int)(dstHeight - padding - p.Y / ratioY));
                dst.Draw(new CircleF(pp, 1), new Bgr(Color.Black), 1);
            }
            if (showMax)
            {
                //绘制最大值
                PointF maxPoint = Util.getMax(pointfs, (obj1, obj2) =>
                {
                    return (int)obj1.Y - (int)obj2.Y;
                });
                Point maxpp = new Point((int)(maxPoint.X / ratioX + padding), (int)(dstHeight - padding - maxPoint.Y / ratioY));
                dst.Draw(new CircleF(maxpp, 3), new Bgr(Color.Red), 5);
                dst.Draw("(" + maxPoint.X + "," + maxPoint.Y + ")", maxpp, Emgu.CV.CvEnum.FontFace.HersheyComplexSmall, 1, new Bgr(Color.Black));
                dst.Draw(new LineSegment2D(new Point(maxpp.X, dstHeight - padding), maxpp), new Bgr(Color.Red), 1);//x
                dst.Draw(new LineSegment2D(new Point(padding, maxpp.Y), maxpp), new Bgr(Color.Red), 1);//y
            }
            if (showMin)
            {
                //绘制最小值
                PointF maxPoint = Util.getMin(pointfs, (obj1, obj2) =>
                {
                    return (int)obj1.Y - (int)obj2.Y;
                });
                Point maxpp = new Point((int)(maxPoint.X / ratioX + padding), (int)(dstHeight - padding - maxPoint.Y / ratioY));
                dst.Draw(new CircleF(maxpp, 3), new Bgr(Color.Red), 5);
                dst.Draw("(" + maxPoint.X + "," + maxPoint.Y + ")", maxpp, Emgu.CV.CvEnum.FontFace.HersheyComplexSmall, 1, new Bgr(Color.Black));
                dst.Draw(new LineSegment2D(new Point(maxpp.X, dstHeight - padding), maxpp), new Bgr(Color.Red), 1);//x
                dst.Draw(new LineSegment2D(new Point(padding, maxpp.Y), maxpp), new Bgr(Color.Red), 1);//y
            }
            if (showConcentratedArea)
            {
                PointF center = new PointF(padding, padding);
                int max = 0;
                foreach (PointF pf1 in pointfs)
                {
                    int n = 0;
                    foreach (PointF pf2 in pointfs)
                    {
                        if (Util.Distance(pf1, pf2) < concentratedAreaRadius)
                        {
                            n++;
                        }
                    }
                    if (n > max)
                    {
                        max = n;
                        center = pf1;
                    }
                }
                center = new PointF(center.X,center.Y);
                //Point pp = new Point((int)(center.X / ratioX + padding), (int)(dstHeight - padding - center.Y / ratioY));

                PointF p = locationConvert(center, ratioX,ratioY);
                CircleF circle = new CircleF(p, concentratedAreaRadius);
                dst.Draw(circle,new Bgr(Color.Red),2);
                dst.Draw(new CircleF(p,2), new Bgr(Color.Red), 2);
                drawIntersection(dst,p,center);
            }
            return dst;
        }
        //坐标转换
        private Point locationConvert(PointF p,double ratioX,double ratioY)
        {
            return new Point((int)(p.X / ratioX + padding), (int)(dstHeight - padding - p.Y / ratioY));
        }
        /// <summary>
        /// 画交点
        /// </summary>
        /// <param name="dst"></param>
        /// <param name="p">转换后的坐标</param>
        /// <param name="realPoint">真实坐标</param>
        private void drawIntersection(Image<Bgr,byte> dst,PointF p,PointF realPoint)
        {
            dst.Draw(new LineSegment2D(new Point((int)p.X, dstHeight - padding),Point.Round( p)), new Bgr(Color.Red), 1);//x
            dst.Draw(new LineSegment2D(new Point(padding, (int)p.Y), Point.Round(p)), new Bgr(Color.Red), 1);//y
            dst.Draw("(" + (int)realPoint.X + "," + (int)realPoint.Y + ")", new Point((int)p.X+15,(int)p.Y), Emgu.CV.CvEnum.FontFace.HersheyComplexSmall,1, new Bgr(Color.Red),1);

        }
    }
}
